package com.model.objects;

import java.util.Iterator;
import java.util.List;
import java.util.Random;
import com.model.logic.Field;
import com.model.logic.Location;
import com.model.logic.Randomizer;

public class Lava implements Actor {

	private Field field;
	private Location location;
	// A shared random number generator to control fire spread.
    private static final Random rand = Randomizer.getRandom();
    // The number of block it can spread per step
	private static final int MAX_SPREAD_SIZE = 2;
	// the probability for a lava to spread
	private static final double SPREAD_PROBABILITY = 0.0115;
    
	/**
     * Create a volcano.
     * 
     * @param randomAge If true, the fox will have random age and hunger level.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
	public Lava(Location location, Field field){
		this.location = location;
		this.field = field;
	}
	
    /**
     * This is what the lava does most of the time: it's spreading.
     * In the process, it might kill rabbits, foxes, crocodiles, hunters or grass
     * @param field The field currently occupied.
     * @param newLavas A list to return newly spread lava.
     */
    public void act(List<Actor> newLavas)
    {
            spreadLava(newLavas);            
            // Move towards a source of food if found.
            Location newLocation = getLocation();
            if(newLocation == null) { 
                // No food found - try to move to a free location.
                newLocation = getField().randomAdjacentLocation(getLocation());
                //findFood();
            }
            // See if it was possible to move.
            if(newLocation != null) {
                setLocation(newLocation);
                killLifeAround();
            }

        
    }
	
    /**
     * Generate a number representing the number of spreads,
     * if it can spread.
     * @return The number of spreads (may be zero).
     */
    private int spread()
    {
        int spread = 0;
        if(rand.nextDouble() <= SPREAD_PROBABILITY) {
            spread = rand.nextInt(MAX_SPREAD_SIZE) + 1;
        }
        return spread;
    }
    
    /**
     * Check whether or not this lava can spread at this step.
     * Lava spread will be made into free adjacent locations.
     * @param newLavas A list to return newly spread lava.
     */
    private void spreadLava(List<Actor> newLavas)
    {
        // New foxes are born into adjacent locations.
        // Get a list of adjacent free locations.
        Field field = getField();
        List<Location> free = field.getFreeAdjacentLocations(getLocation());
        int spread = spread();
        for(int b = 0; b < spread && free.size() > 0; b++) {
            Location loc = free.remove(0);
            Lava young = new Lava(loc, field);
            newLavas.add(young);
        }
    }
    
    /**
     * In case a animal or hunter 
     * gets in contact with the lava, 
     * the lava will kill it
     */
    private void killLifeAround()
    {
        Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
        while(it.hasNext()) {
            Location where = it.next();
            Object actor = field.getObjectAt(where);
            if(actor instanceof Rabbit) {
                Rabbit rabbit = (Rabbit) actor;
                if(rabbit.isAlive()) { 
                    rabbit.setDead();
                }
            }
            else if(actor instanceof Fox) {
                Fox fox = (Fox) actor;
                if(fox.isAlive()) { 
                    fox.setDead();
                }
            }
            else if(actor instanceof Crocodile) {
                Crocodile crocodile = (Crocodile) actor;
                if(crocodile.isAlive()) { 
                    crocodile.setDead();
                }
            }
            else if(actor instanceof Jager) {
                Jager jager = (Jager) actor;
                if(jager.isAlive()) { 
                    jager.setDead();
                }
            }
            else if(actor instanceof Grass) {
                Grass grass = (Grass) actor;
                if(grass.isAlive()) { 
                    grass.setDead();
                }
            }
        }
    }
   
    /**
     * setter for location
     * @param newLocation
     */
	public void setLocation(Location newLocation)
    {
        if(location != null) {
            field.clear(location);
        }
        location = newLocation;
        field.place(this, newLocation);
    }

	/**
	 * return the current location of the lava.
	 * @return location
	 */
	private Location getLocation() {
		return location;
	}

	/**
	 * returns the current field of the lava.
	 * @return field
	 */
	private Field getField() {
		return field;
	}
}
